<?php

class vtnsUser extends sfBasicSecurityUser
{
    private $page_id = false; // false: not computed yet, null: no page_id
    private $page    = false; // false: not computed yet, null: no page
    private $fb_user = null;
    private $is_fan = null, $is_admin = null;


    public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array())
    {
        if (sfContext::getInstance()->getRequest()->hasParameter('signed_request')) {
            $culture = $this->getCultureFromSignedRequest();
            if ($culture)
                $options['culture'] = $culture;
        }

        parent::initialize($dispatcher, $storage, $options);

        // Expires some session attributes, e.g. install data
        foreach ($this->getAttributeHolder()->getAll() as $name => $data)
            if (is_array($data) && !empty($data['expires_at']) && $data['expires_at'] < time())
                $this->getAttributeHolder()->remove($name);
    }

    /*
     * Store into session the attachment_id removed (if present in request).
     * It's needed to later (un)validate the application_form.
     */
    public function addAttachmentToRemovalList(sfRequest $request)
    {
        if ($attachment_id = $request->getParameter('attachment_id')) {
            $list = $this->getAttribute('removed_attachment_list', array());
            if (!is_array($list))
                $list = array();
            $list[] = $attachment_id;
            $this->setAttribute('removed_attachment_list', $list);
            sfContext::getInstance()->getLogger()->info('{uploadAction} Added attachment_id to the <removed_attachment_list> attribute: '.var_export($list,true));
        }
    }

    private function getCultureFromSignedRequest()
    {
        $signed_request = App::getFacebookClient()->getSignedRequest();
        return vtnsCultureInfo::getCultureFromLocale($signed_request['user']['locale']);
    }

    /**
     * Get the current page ID (no page object is created).
     */
    public function getPageId()
    {
        if ($this->page_id !== false)
            return $this->page_id;

        $page_id = sfContext::getInstance()->getRequest()->getParameter('page_id');
        if ($page_id) {
            sfContext::getInstance()->getLogger()->info('{vtnsUser} Page_uid from page_id: '.$page_id);
            $this->page_id = $page_id;
            return $this->page_id;
        }

        sfContext::getInstance()->getLogger()->warning('{vtnsUser} No page id found');
        $this->page_id = null;
        return $this->page_id;
    }


    /**
     * Sets the Page_id.
     */
    public function setPageId($page_id)
    {
        $this->page_id = $page_id;
    }


    /**
     * Get the current page. If this is a new page, it is automatically created,
     * but with basic information only, the installation must be completed for
     * all relevant records to be created.
     */
    public function getPage()
    {
        if ($this->page !== false)
            return $this->page;

        $page_id = $this->getPageId();
        if (!$page_id) {
            $this->page = null;
            return $this->page;
        }

        $conn = Doctrine_Core::getTable('Page')->getConnection();
        $conn->beginTransaction();
        try{
            $this->page = Doctrine::getTable('Page')->find($page_id);
            if (!$this->page) {
                $this->page = new Page();
                $this->page->page_id = $page_id;
                $this->page->save();
            }
            $conn->commit();
        } catch (Exception $e) {
            $conn->rollback();
            throw $e;
        }

        return $this->page;
    }


    /**
     * Returns the uid of the current user.
     *
     * For tabbed profiles, only works in Ajax.
     */
    public function getUid()
    {
        return $this->getAttribute('uid');
    }


    /**
     * Gets the User object for the current uid.
     */
    public function getFbUser()
    {
        if (!$this->fb_user) {
            if ($this->getUid())
                $this->fb_user = Doctrine::getTable('User')->find($this->getUid());
        }
        return $this->fb_user;
    }


    /**
     * Set Facebook User Id of the current User.
     */
    public function setUid($uid)
    {
        $this->setAttribute('uid', $uid);
    }


    /**
     * Sets the User object.
     */
    public function setFbUser($fb_user)
    {
        $this->fb_user = $fb_user;
        $culture = $fb_user->getCulture();
        if ($culture)
            $this->setCulture($culture);
    }

    private function hasPermission($permission, $is_page_permission)
    {
        if ($is_page_permission && !in_array($permission, array('publish_stream', 'manage_pages')))
            throw new Exception("{myUser} Unsupported page permission '$permission'");
        else if (!in_array($permission, array('email', 'publish_stream')))
            throw new Exception("{myUser} Unsupported user permission '$permission'");

        if ($is_page_permission)
            $uid = $this->getPageId();
        else
            $uid = $this->getUid();

        try {
            $result = App::call_api(array(
                    'method' => 'fql.query',
                    'query'  => "SELECT $permission FROM permissions WHERE uid = $uid",
                    ));
        } catch (Exception $e) {
            return false;
        }

        if (is_array($result) && isset($result[0][$permission]))
            return (bool) $result[0][$permission];
        else
            return false;
    }
    /**
     * TODO: use the JS SDK when possible
     */
    public function hasUserPermission($permission)
    {
        $result = $this->hasPermission($permission, false);
        sfContext::getInstance()->getLogger()->debug("{myUser} hasUserPermission('$permission'): ".($result ? 'true' : 'false'));
        return $result;
    }


    /**
     * TODO: use the JS SDK when possible
     */
    public function hasPagePermission($permission)
    {
        $result = $this->hasPermission($permission, true);
        sfContext::getInstance()->getLogger()->debug("{myUser} hasPagePermission('$permission'): ".($result ? 'true' : 'false'));
        return $result;
    }


    public function hasRemovedAttachment($attachment_id)
    {
        $list = $this->getAttribute('removed_attachment_list', array());
        sfContext::getInstance()->getLogger()->info('{myUser} Retrieved the <removed_attachment_list> attribute: '.var_export($list,true));
        return (is_array($list) && in_array($attachment_id, $list));
    }

    public function isAdmin()
    {
        if (null === $this->is_admin) {
            $this->is_admin = $this->getFbUser() && $this->getFbUser()->isAdmin();
        }
        return $this->is_admin;
    }

    public function setIsAdmin($value)
    {
        $this->is_admin = (bool) $value;
    }

    public function isCustomer()
    {
        return $this->getFbUser() && $this->getFbUser()->isCustomer();
    }

    public function isFan()
    {
        if (null === $this->is_fan) {
            $signed_request = App::getFacebookClient()->getSignedRequest();
            if ($signed_request && isset($signed_request['page']))
                $this->is_fan = $signed_request['page']['liked'];
        }
        return $this->is_fan;
    }

    public function isLinkedInAuthorized()
    {
        $uid = $this->getUid();
        return $uid && LinkedInApiTokens::isAuthorizedForUid($uid);
    }

    public function isSmartPage()
    {
        return $this->getPage() && $this->getPage()->isSmartPage();
    }


    public function logOut()
    {
        $this->setAuthenticated(false);
        $this->setAttribute('uid', null);
        $this->setAttribute('page_ids', null);
    }


    public function logIn($uid)
    {
        $this->setAuthenticated(true);

        // Do not erase page_ids if possible
        if ($this->getAttribute('uid') !== $uid) {
            $this->setAttribute('uid', $uid);
            $this->setAttribute('page_ids', array());
        }
    }
}

